﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using MySql.Data.MySqlClient;

using Lucene.Net.Index;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using System.Data;

namespace com.tiyma.components
{
    public class BookIndexManager
    {

        /// <summary>
        /// 服务调用
        /// </summary>
        public void CreateBookIndexByService()
        {
            while (true)
            {
                if (DateTime.Now.Hour == 3 && DateTime.Now.Minute == 0)
                {
                    CreateBookIndex();

                    System.Threading.Thread.Sleep(10* 60 * 1000);

                }
                System.Threading.Thread.Sleep(100);

              
            }
        }

      

        /// <summary>
        /// 创建图书索引
        /// </summary>
        public void CreateBookIndex()
        {
            LogHelper.Info("开始创建图书索引...");

            DateTime t_dt_start = DateTime.Now;

            string t_book_index_path = AppConfig.BookIndexPathTemp;

            if (!Directory.Exists(t_book_index_path))
            {
                Directory.CreateDirectory(t_book_index_path);
            }

            DirectoryInfo t_dic_file_info=new DirectoryInfo(t_book_index_path);
            foreach (System.IO.FileInfo t_file in t_dic_file_info.GetFiles())
            {
                t_file.Delete();
            }

            IndexWriter t_write = null;

            t_write = new IndexWriter(t_book_index_path, new Lucene.Net.Analysis.Standard.StandardAnalyzer(), true);
            t_write.SetMergeFactor(1000);
            t_write.SetMaxBufferedDocs(1000);
            t_write.SetUseCompoundFile(false);

            string t_str_sql = "select bookId,bookName,authorName,categoryName,subCategoryName,description" +
                            ",lastUpdateChapterId,lastUpdateChapterName,lastUpdateTime" +
                            ",chapterCount,siteId,siteName,status,(select clickcount from tbbookclick b where a.bookId=b.bookId) clickcount " +
                            "from tbbook a where a.lastUpdateTime is not null and a.siteid!=5 order by a.lastUpdateTime desc";

            try
            {
                BookInfo t_book = null;

                DateTime t_last_update_time = DateTime.Now;

                int t_chapter_count = 0;

                int t_site_id = 0;

                using (SqlConnection t_connection = new SqlConnection(AppConfig.SqlConnectionString))
                {
                    using (SqlCommand t_cmd = new SqlCommand(t_str_sql, t_connection))
                    {
                      
                        t_cmd.CommandTimeout = 600;
                        t_connection.Open();
                        using (SqlDataReader t_reader = t_cmd.ExecuteReader(CommandBehavior.CloseConnection))
                        {

                            while (t_reader.Read())
                            {
                                t_book = new BookInfo();
                                t_book.BookId = t_reader["bookId"].ToString();
                                t_book.AuthorName = t_reader["authorName"].ToString();
                                t_book.BookName = t_reader["bookName"].ToString();
                                t_book.Description = t_reader["description"].ToString();
                                t_book.BookCategory = t_reader["categoryName"].ToString();
                                t_book.BookSubCategory = t_reader["subCategoryName"].ToString();
                                t_book.LastUpdateChapterId = t_reader["lastUpdateChapterId"].ToString();
                                t_book.LastUpdateChapterName = t_reader["lastUpdateChapterName"].ToString();

                                if (!DateTime.TryParse(t_reader["lastUpdateTime"].ToString(), out t_last_update_time))
                                    t_last_update_time = DateTime.Now;

                                t_book.LastUpdateTime = t_last_update_time;

                                if (!int.TryParse(t_reader["chapterCount"].ToString(), out t_chapter_count))
                                    t_chapter_count = 0;
                                t_book.BookChapterCount = t_chapter_count;

                                if (!int.TryParse(t_reader["siteId"].ToString(), out t_site_id))
                                    t_site_id = 0;

                                t_book.SiteId = t_site_id;
                                t_book.SiteName = t_reader["siteName"].ToString();
                                t_book.IsVip = t_reader["status"].ToString().Equals("3") ? true : false;
                                int t_click_count = 0;
                                if (t_reader["clickcount"] != DBNull.Value)
                                {
                                    if (!int.TryParse(t_reader["clickcount"].ToString(), out t_click_count))
                                        t_click_count = 0;

                                }
                                t_book.ClickCount = t_click_count;
                                CreateBookIndexData(t_write, t_book);

                            }
                            
                        }
                    }
                }

                t_write.Optimize();
                t_write.Close();

                TimeSpan t_sp = DateTime.Now.Subtract(t_dt_start);
                LogHelper.Info(string.Format("创建完毕,总共花了{0}秒。", t_sp.Seconds));

                LogHelper.Info("开始移动文件...");

                t_book_index_path = AppConfig.BookIndexPath;
                t_dic_file_info = new DirectoryInfo(t_book_index_path);
                foreach (System.IO.FileInfo t_file in t_dic_file_info.GetFiles())
                {
                    t_file.Delete();
                }
                t_book_index_path = AppConfig.BookIndexPathTemp;
                t_dic_file_info = new DirectoryInfo(t_book_index_path);
                foreach (System.IO.FileInfo t_file in t_dic_file_info.GetFiles())
                {
                    t_file.MoveTo(Path.Combine(AppConfig.BookIndexPath, t_file.Name));
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error("创建图书索引失败" + ex.ToString());
            }
            finally
            {
                if (t_write != null)
                    t_write.Close();
            }
        }

        /// <summary>
        /// 创建小说索引，只对书名、作者名、一级分类、二级分类、简介创建综合索引
        /// </summary>
        /// <param name="i_writer"></param>
        /// <param name="i_book"></param>
        private void CreateBookIndexData(IndexWriter i_writer, BookInfo i_book)
        {
            try
            {
                Document doc = new Document();



                doc.Add(new Field("BOOKID", i_book.BookId, Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("BOOKNAME", i_book.BookName, Field.Store.YES, Field.Index.ANALYZED));
                doc.Add(new Field("AUTHORNAME", i_book.AuthorName, Field.Store.YES, Field.Index.ANALYZED));
                doc.Add(new Field("BOOKCATEGORY", i_book.BookCategory, Field.Store.YES, Field.Index.ANALYZED));
                doc.Add(new Field("BOOKSUBCATEGORYNAME", i_book.BookSubCategory, Field.Store.YES, Field.Index.ANALYZED));
                doc.Add(new Field("DESCRIPTION", i_book.Description, Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("LASTUPDATECHAPTERID", i_book.LastUpdateChapterId, Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("LASTUPDATECHAPTERNAME", i_book.LastUpdateChapterName, Field.Store.YES, Field.Index.NOT_ANALYZED));
                Field t_field_updatetime = new Field("LASTUPDATETIME", i_book.LastUpdateTime.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED);
                doc.Add(t_field_updatetime);

                int t_chapter_count = i_book.BookChapterCount;

                Field t_field_book_chapter_count = new Field("BOOKCHAPTERCOUNT", t_chapter_count.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED);
                doc.Add(t_field_book_chapter_count);

                Field t_field_book_click_count = new Field("CLICKCOUNT", i_book.ClickCount.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED);
                doc.Add(t_field_book_click_count);
        
                doc.Add(new Field("SITEID", i_book.SiteId.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("SITENAME", i_book.SiteName.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.Add(new Field("ISDOWNLOAD", "1", Field.Store.YES, Field.Index.NOT_ANALYZED));
             
                i_writer.AddDocument(doc);
            }
            catch (Exception ex)
            {
                LogHelper.Error("创建小说索引失败" + ex.ToString());
            }
        }

        //文本过滤
        private string FiltrateContent(string i_text)
        {
            i_text = Regex.Replace(i_text, @"<[\s|\S]*?>", " ", RegexOptions.Compiled);
            i_text = Regex.Replace(i_text, @"\s+", " ", RegexOptions.Compiled);
            i_text = Regex.Replace(i_text, @"document\.write", " ", RegexOptions.Compiled);
            i_text = Regex.Replace(i_text, @"&nbsp;", " ", RegexOptions.Compiled);
            i_text = i_text.Replace("<", "&lt;").Replace(">", "&gt;").Replace("&", "&amp;");
            return i_text;
        }


        /// <summary>
        /// 根据最后章节名称获取章节总数
        /// </summary>
        /// <param name="i_chapter_count"></param>
        /// <param name="i_last_update_chapter_name"></param>
        /// <returns></returns>
        public int GetChapterCount(int i_chapter_count, string i_last_update_chapter_name)
        {

            if (string.IsNullOrEmpty(i_last_update_chapter_name))
                return i_chapter_count;


            string[] t_big_chinese = new string[] { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "拾", "佰", "仟", "〇" };
            string[] t_small_chinese = new string[] { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "百", "千", "〇" };
            string[] t_number = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "十", "百", "千", "0" };

            for (int index = 0; index < t_big_chinese.Length; index++)
            {

                i_last_update_chapter_name = i_last_update_chapter_name.Replace(t_big_chinese[index], t_number[index]);
                i_last_update_chapter_name = i_last_update_chapter_name.Replace(t_small_chinese[index], t_number[index]);
            }

            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)千(\\d+)百(\\d+)十(\\d+)", "$1$2$3$4", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)千(\\d+)百(\\d+)", "$1$2$3", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)千(\\d+)", "$1$2", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)千", "$1^000", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)百(\\d+)十(\\d+)", "$1$2$3", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)百(\\d+)", "$1$2", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)百", "$1^00", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)十(\\d+)", "$1$2", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "(\\d+)十", "$1^0", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            i_last_update_chapter_name = Regex.Replace(i_last_update_chapter_name, "十(\\d+)", "1$1", RegexOptions.IgnoreCase | RegexOptions.Compiled);

            i_last_update_chapter_name = i_last_update_chapter_name.Replace("^", "").Replace("十", "10");

            Match t_mc = Regex.Match(i_last_update_chapter_name, "(\\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
            if (t_mc != null && t_mc.Groups.Count > 1)
            {
                int t_chapter_count = 0;
                if (!int.TryParse(t_mc.Groups[1].Value.ToString(), out t_chapter_count))
                    t_chapter_count = 0;

                if (t_chapter_count != 0)
                    return t_chapter_count;
            }

            return i_chapter_count;

        }

        //根据最后更新日期调节排序权重
        public float SetDateTimeBoost(DateTime i_last_update_time)
        {
            float t_boost = 0.0f;
            System.DateTime dt = i_last_update_time;
            System.DateTime now = System.DateTime.Now;

            System.TimeSpan ts = now - dt;
            int days = ts.Days;
            if (days <= 3)                         //小于3天
                t_boost = 134.297f;
            if (days > 3 && days <= 6)             //大于3天小于7天
                t_boost = 99.4665f;
            if (days > 6 && days <= 9)
                t_boost = 73.6788f;
            if (days > 9 && days <= 15)
                t_boost = 54.57693f;
            if (days > 15 && days <= 25)
                t_boost = 40.4274f;
            if (days > 25 && days <= 35)
                t_boost = 29.9462f;
            if (days > 35 && days <= 45)
                t_boost = 22.18236f;
            if (days > 45 && days <= 60)
                t_boost = 16.43138f;
            if (days > 60 && days <= 80)
                t_boost = 12.17139f;
            if (days > 80 && days <= 100)
                t_boost = 9.01584f;
            if (days > 100 && days <= 150)
                t_boost = 6.678405f;
            if (days > 150 && days <= 200)             //大于3天小于7天
                t_boost = 4.946967f;
            if (days > 200 && days <= 250)
                t_boost = 3.6644f;
            if (days > 250 && days <= 300)
                t_boost = 2.7143f;
            if (days > 300 && days <= 360)
                t_boost = 2.0106f;
            if (days > 360 && days <= 420)
                t_boost = 1.4896f;
            if (days > 420 && days <= 480)
                t_boost = 1.10324f;
            if (days > 480 && days <= 540)
                t_boost = 0.817215f;
            if (days > 540 && days <= 640)
                t_boost = 0.60534f;
            if (days > 640 && days <= 740)
                t_boost = 0.4484f;
            if (days > 740 && days <= 840)
                t_boost = 0.3321f;
            if (days > 840 && days <= 940)
                t_boost = 0.2464f;
            if (days > 940 && days <= 1040)
                t_boost = 0.1825f;
            if (days > 1040 && days <= 1500)
                t_boost = 0.135f;
            if (days > 1500)
                t_boost = 0.1f;
            return t_boost;
        }
    }
}
